package com.blog.kit;

import com.jfinal.kit.StrKit;
import org.apache.log4j.Logger;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

/**
 * 字符串工具类
 *
 * Created by wangjian on 16/9/14.
 */
public class StringKit {

    public static final Logger logger = Logger.getLogger(StringKit.class.getName());
    public static final StringKit kit = new StringKit();

    /**
     * 清理字符串，清理出某些不可见字符
     *
     * @param txt
     * @return {String}
     */
    public static String cleanChars(String txt) {

        return txt.replaceAll("[ 　	`·•�\\f\\t\\v]", "");
    }

    // 随机字符串
    private static final String _INT = "0123456789";
    private static final String _STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    private static final String _ALL = _INT + _STR;
    private static final Random RANDOM = new Random();

    /**
     * 生成的随机数类型
     *
     * @author L.cm
     * @email: 596392912@qq.com
     * @site: http://www.dreamlu.net
     * @date 2015年4月20日下午9:15:23
     */
    public static enum RandomType {

        INT, STRING, ALL;
    }

    /**
     * 随机数生成
     *
     * @param count
     * @return
     */
    public static String random(int count, RandomType randomType) {

        if (count == 0) return "";
        if (count < 0) {
            throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
        }
        char[] buffer = new char[count];
        for (int i = 0; i < count; i++) {
            if (randomType.equals(RandomType.INT)) {
                buffer[i] = _INT.charAt(RANDOM.nextInt(_INT.length()));
            } else if (randomType.equals(RandomType.STRING)) {
                buffer[i] = _STR.charAt(RANDOM.nextInt(_STR.length()));
            } else {
                buffer[i] = _ALL.charAt(RANDOM.nextInt(_ALL.length()));
            }
        }
        return new String(buffer);
    }

    /**
     * 手机号码隐藏
     *
     * @param phone
     * @return
     */
    public static String hidePhone(String phone) {

        if (StrKit.isBlank(phone)) {
            return "";
        } else if (RegexKit.match("^[+]?[0-9]{0,4}1[3|4|5|7|8][0-9]{9}$", phone)) {
            String begin = phone.substring(0, 3);
            String end = phone.substring(7, phone.length());
            return begin + "****" + end;
        } else {
            return phone;
        }
    }

    /**
     * 邮箱隐藏
     *
     * @param mail
     * @return
     */
    public static String hideMail(String mail) {
        if (StrKit.isBlank(mail)) {
            return "";
        } else if (!RegexKit.match("\\b(^[\'_A-Za-z0-9-]+(\\.[\'_A-Za-z0-9-]+)*@([A-Za-z0-9-])+(\\.[A-Za-z0-9-]+)*((\\.[A-Za-z0-9]{2,})|(\\.[A-Za-z0-9]{2,}\\.[A-Za-z0-9]{2,}))$)\\b", mail)) {
            return mail;
        } else {
            String prefixMail = mail.substring(0, mail.indexOf("@"));
            BigDecimal lengthBigDecimal = new BigDecimal(prefixMail.length());
            BigDecimal halfCeilLength = lengthBigDecimal.divide(new BigDecimal(2)).setScale(0, 4);
            BigDecimal halfFloorLength = lengthBigDecimal.divide(new BigDecimal(2)).setScale(0, 5);
            String front = prefixMail.substring(0, halfFloorLength.intValue() / 2);
            String end = prefixMail.substring(halfFloorLength.intValue() / 2 + halfCeilLength.intValue(), prefixMail.length());
            StringBuffer middle = new StringBuffer("");

            for (int i = 0; i < halfCeilLength.intValue(); ++i) {
                middle.append("*");
            }

            return front + middle + end + mail.substring(mail.indexOf("@"));
        }
    }

    /**
     * 身份证号码隐藏
     *
     * @param idCard
     * @return
     */
    public static String hideIdCard(String idCard) {
        if (StrKit.isBlank(idCard)) {
            return "";
        } else if (RegexKit.match("^\\d{15}$|^\\d{17}([0-9]|X)$", idCard)) {
            String begin = idCard.substring(0, 6);
            String end = idCard.substring(14, idCard.length());
            return begin + "********" + end;
        } else {
            return idCard;
        }
    }

    /**
     * 首字母变小写
     */
    public static String firstCharToLowerCase(String str) {

        char firstChar = str.charAt(0);
        if (firstChar >= 'A' && firstChar <= 'Z') {
            char[] arr = str.toCharArray();
            arr[0] += ('a' - 'A');
            return new String(arr);
        }
        return str;
    }

    /**
     * 首字母变大写
     */
    public static String firstCharToUpperCase(String str) {

        char firstChar = str.charAt(0);
        if (firstChar >= 'a' && firstChar <= 'z') {
            char[] arr = str.toCharArray();
            arr[0] -= ('a' - 'A');
            return new String(arr);
        }
        return str;
    }

    /**
     * 字符串为 null 或者为  "" 时返回 true
     */
    public static boolean isBlank(String str) {
        return str == null || "".equals(str.trim());
    }

    /**
     * 字符串不为 null 而且不为  "" 时返回 true
     */
    public static boolean notBlank(String str) {
        return str != null && !"".equals(str.trim());
    }

    /**
     * MD5加密（32位\16位可选）
     *
     * @param str
     * @return
     */
    public static String MD5(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            byte b[] = md.digest();

            int i;

            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0)
                    i += 256;
                if (i < 16)
                    buf.append("0");
                buf.append(Integer.toHexString(i));
            }
            //32位加密
            return buf.toString();
            // 16位的加密
            //return buf.toString().substring(8, 24);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * 获取一个字符串的简明效果
     * @return String 返回的字符串格式类似于"abcd***hijk"
     */
    public static String getStringSimple(String data){

        return data.substring(0,4) + "***" + data.substring(data.length()-4);
    }

    /**
     * 判断输入的字符串参数是否为空
     * @return boolean 空则返回true,非空则flase
     */
    public static boolean isEmpty(String input) {

        return null==input || 0==input.length() || 0==input.replaceAll("\\s", "").length();
    }

    /**
     * 判断输入的字节数组是否为空
     * @return boolean 空则返回true,非空则flase
     */
    public static boolean isEmpty(byte[] bytes){

        return null==bytes || 0==bytes.length;
    }

    /**
     * 字节数组转为字符串
     * 如果系统不支持所传入的charset字符集,则按照系统默认字符集进行转换
     */
    public static String getString(byte[] data, String charset){

        if(isEmpty(data)){
            return "";
        }
        if(isEmpty(charset)){
            return new String(data);
        }
        try {
            return new String(data, charset);
        } catch (UnsupportedEncodingException e) {
            logger.error("将byte数组[" + data + "]转为String时发生异常:系统不支持该字符集[" + charset + "]");
            return new String(data);
        }
    }

    /**
     * 字符串转为字节数组
     * 如果系统不支持所传入的charset字符集,则按照系统默认字符集进行转换
     */
    public static byte[] getBytes(String data, String charset){

        data = (data==null ? "" : data);
        if(isEmpty(charset)){
            return data.getBytes();
        }
        try {
            return data.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            logger.error("将字符串[" + data + "]转为byte[]时发生异常:系统不支持该字符集[" + charset + "]");
            return data.getBytes();
        }
    }

    /**
     * 判断一个字符串在数组中存在几个
     *
     * @param baseStr
     * @param strings
     * @return
     */
    public static int stringIndexOfArray(String baseStr,String[] strings){

        if(null == baseStr || baseStr.length() == 0 || null == strings)
            return 0;

        int i = 0;
        for (String string : strings) {
            boolean result = baseStr.equals(string);
            i = result ? ++i : i;
        }
        return i ;
    }
}
